<script lang="ts" setup>
import { ref, watch } from 'vue';

import { ElMessage, ElUpload } from 'element-plus';

const emits = defineEmits(['change']);
const modelValue = defineModel<(Blob | object | string)[]>('modelValue', {
  default: [],
});
const videoList = ref<any[]>([]);
const isProcessing = ref(false);

// 视频配置
const videoConfig = ref({
  maxSize: 100 * 1024 * 1024, // 最大文件大小（100MB）
  maxDuration: 300, // 最大时长（秒）
  acceptedFormats: ['video/mp4', 'video/webm'], // 支持的格式
});
// 生成视频缩略图
const generateThumbnail = (file: File) => {
  return new Promise<string>((resolve, reject) => {
    const video = document.createElement('video');
    const canvas = document.createElement('canvas');
    const url = URL.createObjectURL(file);

    video.src = url;
    video.preload = 'metadata';

    video.addEventListener('loadedmetadata', () => {
      video.currentTime = 1; // 截取第1秒的画面
    });

    video.addEventListener('seeked', () => {
      canvas.width = video.videoWidth;
      canvas.height = video.videoHeight;
      canvas
        .getContext('2d')
        ?.drawImage(video, 0, 0, canvas.width, canvas.height);
      const dataUrl = canvas.toDataURL('image/jpeg');
      URL.revokeObjectURL(url);
      resolve(dataUrl);
    });

    video.onerror = (error) => {
      URL.revokeObjectURL(url);
      reject(error);
    };
  });
};

// 处理视频文件
const processVideo = (file: File) => {
  return new Promise<File>((resolve, reject) => {
    // 检查文件格式
    if (!videoConfig.value.acceptedFormats.includes(file.type)) {
      reject(new Error('不支持的视频格式，请上传MP4或WebM格式'));
      return;
    }

    // 检查文件大小
    if (file.size > videoConfig.value.maxSize) {
      reject(new Error('视频文件过大，请上传小于100MB的文件'));
      return;
    }

    // 检查视频时长
    const video = document.createElement('video');
    video.preload = 'metadata';

    video.addEventListener('loadedmetadata', () => {
      URL.revokeObjectURL(video.src);

      if (video.duration > videoConfig.value.maxDuration) {
        reject(new Error('视频时长超过5分钟限制'));
        return;
      }

      resolve(file);
    });

    video.onerror = () => {
      URL.revokeObjectURL(video.src);
      reject(new Error('视频文件损坏或格式不正确'));
    };

    video.src = URL.createObjectURL(file);
  });
};

// 处理视频上传
const onChange = async (uploadFile) => {
  try {
    isProcessing.value = true;
    const rawFile = uploadFile.raw;

    // 处理视频
    // const processedFile = await processVideo(rawFile);
    // const previewUrl = URL.createObjectURL(processedFile);
    // const thumbnailUrl = await generateThumbnail(processedFile);
    // const thumbnailUrl = '';

    // // 更新预览列表
    // videoList.value.push({
    //   preview: uploadFile,
    //   thumbnail: thumbnailUrl,
    //   name: uploadFile.name,
    //   rawFile: uploadFile,
    //   progress: 0,
    // });

    // 更新model值
    modelValue.value = [
      ...modelValue.value,
      {
        videoUrl: uploadFile,
        videoOssObjectKey: '',
      },
    ];

    // 发出变更事件
    // emits('change', {
    //   previewUrl,
    //   file: uploadFile,
    // });

    // 替换原始文件
    // uploadFile.raw = processedFile;
  } catch (error) {
    ElMessage.error(error.message || '视频处理失败');
  } finally {
    isProcessing.value = false;
  }
};

// 移除视频
const removeVideo = (index: number) => {
  videoList.value.splice(index, 1);
  modelValue.value.splice(index, 1);
};

// 监听modelValue变化
watch(
  modelValue,
  (newValue) => {
    console.log('newValue', newValue);
    if (newValue.length === 0) {
      videoList.value = [];
    } else {
      videoList.value = newValue.map((item) => {
        console.log('item', item);
        // 区分字符串和Blob(File)类型
        return typeof item.videoUrl === 'string'
          ? {
              preview: item.videoUrl,
              name: item.videoUrl.split('/').pop(),
              rawFile: item.videoUrl,
            }
          : {
              preview: URL.createObjectURL(item.videoUrl.raw),
              name: item.videoUrl.name,
              rawFile: item.videoUrl,
            };
      });
    }
  },
  { deep: true },
);

// 拖拽排序相关方法
const handleDragStart = (event, file) => {
  const index = videoList.value.indexOf(file);
  event.dataTransfer.setData('index', index.toString());
};

const handleDrop = (event, file) => {
  const index = videoList.value.indexOf(file);
  event.preventDefault();

  const draggedIndex = Number(event.dataTransfer.getData('index'));
  const updatedList = [...videoList.value];

  const [draggedItem] = updatedList.splice(draggedIndex, 1);
  updatedList.splice(index, 0, draggedItem);

  videoList.value = updatedList;
  modelValue.value = updatedList.map((item) => item.rawFile);
};
</script>
<template>
  <div class="video-upload">
    <ElUpload
      :auto-upload="false"
      :disabled="isProcessing"
      :on-change="onChange"
      :show-file-list="false"
      accept="video/mp4,video/webm"
      action="#"
      class="upload-demo"
      drag
      multiple
    >
      <div class="flex w-full justify-center">
        <div>
          <div class="el-upload__text">
            {{ isProcessing ? '正在处理...' : '拖拽或点击上传视频' }}
          </div>
          <div class="el-upload__tip">
            支持MP4/WebM格式，大小不超过100MB，时长不超过5分钟
          </div>
        </div>
      </div>
    </ElUpload>

    <!-- 视频预览列表 -->
    <div v-if="videoList.length > 0" class="preview-list">
      <div
        v-for="(video, index) in videoList"
        :key="index"
        class="preview-item"
        draggable="true"
        @dragover.prevent
        @dragstart="handleDragStart($event, video)"
        @drop="handleDrop($event, video)"
      >
        <!-- 视频缩略图 -->
        <video
          :alt="video.name"
          :src="video.preview"
          class="preview-image"
          controls
        ></video>

        <!-- 播放按钮 -->
        <!-- <div
          class="play-button"
          @click="
            () =>
              typeof window !== 'undefined' &&
              window.open(video.preview, '_blank')
          "
        >
          <div class="play-icon">▶</div>
        </div> -->

        <!-- 进度条 -->

        <div class="preview-info">
          <span class="preview-name">{{ video.name }}</span>
        </div>

        <div class="preview-remove" @click.stop="removeVideo(index)">
          <i class="el-icon-delete">×</i>
        </div>
      </div>
    </div>
  </div>
</template>
<style scoped>
.video-upload {
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
}

.upload-area {
  width: 100%;
  padding: 40px;
  text-align: center;
  cursor: pointer;
  border: 2px dashed #ddd;
  border-radius: 6px;
  transition: border-color 0.3s;
}

.upload-area:hover:not([disabled]) {
  border-color: #409eff;
}

.el-upload__tip {
  margin-top: 10px;
  font-size: 12px;
  color: #909399;
}

.preview-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 20px;
  margin-top: 20px;
}

.preview-item {
  position: relative;
  overflow: hidden;
  border-radius: 6px;
  box-shadow: 0 2px 12px rgb(0 0 0 / 10%);
}

.preview-image {
  width: 100%;
  height: 150px;
  object-fit: cover;
}

.preview-info {
  padding: 12px;
  background: #f5f7fa;
}

.preview-name {
  display: block;
  overflow: hidden;
  font-size: 14px;
  color: #606266;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.preview-remove {
  position: absolute;
  top: 5px;
  right: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  color: white;
  cursor: pointer;
  background: rgb(0 0 0 / 50%);
  border-radius: 50%;
  opacity: 0;
  transition: opacity 0.3s;
}

.preview-item:hover .preview-remove {
  opacity: 1;
}

.play-button {
  position: absolute;
  top: 50%;
  left: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 50px;
  height: 50px;
  cursor: pointer;
  background: rgb(0 0 0 / 50%);
  border-radius: 50%;
  transition: background-color 0.3s;
  transform: translate(-50%, -50%);
}

.play-button:hover {
  background: rgb(0 0 0 / 70%);
}

.play-icon {
  font-size: 24px;
  color: white;
}

.upload-progress {
  /* position: absolute;
  right: 0;
  bottom: 0;
  left: 0; */
}

/* 处理状态样式 */
.upload-area[disabled] {
  cursor: not-allowed;
  opacity: 0.7;
}
</style>
